function __isObject(obj) {
  return typeof obj === "object" && obj !== null;
}

const effectMap = new Map(); // {key: Set}
let activeEffect = null;

// 收集依赖
// track:追踪
const track = (key) => {
  if (!activeEffect) return;
  // ******添加副作用函数

  const effectSet = effectMap[key];

  if (effectSet) {
    effectSet.add(activeEffect);
  } else {
    effectMap.set(key, new Set([activeEffect]));
  }
};

// 发布订阅
// trigger:触发
const trigger = (key) => {
  // ******执行对应的prop的所有副作用函数
  const effectSet = effectMap[key];
  if (effectSet) {
    effectSet.forEach((fn) => fn());
  }
};

function reactive(obj) {
  return new Proxy(obj, {
    get(target, prop) {
      track(prop);
      return target[prop];
    },
    set(target, prop, value) {
      if (__isObject(value)) {
        target[prop] = reactive(value);
      } else {
        target[prop] = value;
      }

      trigger(prop);
      return true;
    },
  });
}
const state = reactive({ name: "soup", age: 2 });

// 注册副作用函数
const effect = (fn) => {
  if (typeof fn !== "function") {
    return;
  }

  activeEffect = fn;
  fn();
  activeEffect = null;
};

const effectName = () => {
  console.log("页面调用name:", state.name);
};
const effectName1 = () => {
  console.log("页面调用name1:", state.name);
};

const effectAge = () => {
  console.log("页面调用age:", state.age);
};

// 给属性name设置两个副作用函数，给属性age设置一个副作用函数
effect(); // 打印：页面调用name: soup
effect(effectName1); // 打印： 页面调用name1: soup
effect(effectAge); // 打印：页面调用age: 2

// 改变name的值，只执行name的副作用函数
state.name = "张三"; // 打印：页面调用name: 张三 页面调用name1: 张三

// 因为，代理对象递归代理原对象的所有属性和新增属性
// 所有可以测试下新添加属性是否也可以执行副作用函数
state.like = {
  person: "冬瓜",
  age: 20,
};
const effectPerson = () => {
  console.log("页面调用了person:", state.like.person);
};
effect(effectPerson); // 打印：页面调用了person: 冬瓜
state.like.person = "冬瓜汤"; // 打印：页面调用了person: 冬瓜汤
window.__state = state;

// 会产生一个问题：
// 如果这个对象存在相同的key，就会放在同一个effectMap[key]中
// 或者不同对象存在相同的key，也会放在同一个effectMap[key]中
const effectPersonName = () => {
  console.log("页面调用了person.age:", state.like.age);
};
effect(effectPersonName);

console.log("--------------分割线-----------");

state.like.age = 21; // 打印：页面调用age: 2  页面调用了person.age: 21
// 第一个打印是 state.age 的副作用函数 第二打印才是state.like.age的副作用函数

// 我需要的是就算有重复的key值，也只执行到对应的副作用函数
// 针对不同对象存在相同的key，也会放在同一个effectMap[key]中的解决方法：
// 进入终版 ./reactive/index.js

